package top.suven.base.util.createcode;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.core.annotation.AnnotationUtils;
import top.suven.base.http.JsonParse;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * @Title: CreateCodeDoc.java
 * @author Joven.wang
 * @date 2017年1月19日
 * @version V1.0
 * @Description: TODO(说明)
 */

public class CreateCodeDoc {

	private static Map<String, Object> dataMap = new LinkedHashMap<String, Object>();
	private static int index = 1;

	public static void main(String[] args) {
//		Class xxx = ReportLogRequest.class;
		
//		 for (int i = 0; i <list.size(); i++) {
//			 
//			 //createCode(list.get(i), module);
//		 }
//		createCode(GetAddressInfoVo.class);
//		getCreateFile();
		String d = "中国人ab";
		System.out.println(d.getBytes().length);
//		d  = formatStr(d,10);
//		System.out.println("<<<<<<<"+d+"<<<<<<<");
//		d  = formatStr("12345678",10);
//		System.out.println("<<<<<<<"+d+"<<<<<<<");
		createDataTableMd();

	}
	
	
	
	public static void createDoc(Class<?> claxx)throws Exception{
		Map<String, Class> map = getCreateFile(claxx);
		boolean isContains = true;
		for (String s : map.keySet()) {
			String name = claxx.getSimpleName();
//			System.out.println("xxx.getSimpleName =:" + name);
			if(s.contains(name) || isContains){
				Class ccc = map.get(s);
				createCode(ccc);
			}
			
		}
	}

	

	
	
	private static LinkedHashMap<String, Class> getCreateFile(Class obj) {
		String packageName = obj.getPackage().getName();
		String currentPath = Class.class.getClass().getResource("/").getFile() .toString();
		String packFile = currentPath + packageName.replaceAll("\\.", "/");

		File f = new File(packFile);
		String fileNames[] = f.list();
		LinkedHashMap<String, Class> map = new LinkedHashMap<>();
		List<Class> list = new ArrayList<Class>();
		for (String fileName : fileNames) {
			try {
				if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf("$") > 0) {
					String prefix = fileName.substring(0, fileName.lastIndexOf("."));
					String clazz = packageName + "." + prefix;
					Class classes = CreateCode.class.getClassLoader() .loadClass(clazz);
					list.add(classes);
					map.put(prefix, classes);

				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		System.out.println(map.toString());
		return map;
	}

	public static void createCode(Class<?> entityClazz) {

		try {
			createCode(entityClazz, true,"","default.md");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

    public static void createCode(Class<?> entityClazz,String commentFileName) {

		try {
			createCode(entityClazz, true,"",commentFileName);
		} catch (Exception e) {
			e.printStackTrace();
		}
    }

    public static void createCode(Class<?> entityClazz,String module,String commentFileName) {
		try {
			createCode(entityClazz, true,module,commentFileName);
		} catch (Exception e) {
			e.printStackTrace();
		}

    }

	public static void createCode(Class<?> entityClazz, boolean superclass,String module,String commentFileName)throws Exception {
		dataMap.clear();
		dataMap.put("module", module);
		dataMap.put("baseResponse", "\t");
		dataMap.put("baseClass", " \t");
		dataMap.put("body", "");
		dataMap.put("bodyType", "");
		dataMap.put("response", "");
		dataMap.put("urlNo", index);
		dataMap.put("urldesc","");
		dataMap.put("url","");
        dataMap.put("commentFileName",commentFileName);
		
		initMap(entityClazz,superclass);
		System.out.println(dataMap.toString());

		createServerImpl();
	}

	public static <T> void initMap(Class<T> entityClazz,boolean superclass) {
//		List<Field> flist = new ArrayList<>();
//
//		if (entityClazz.getGenericSuperclass() != null) {
//			Class superClass = entityClazz.getSuperclass();// 父类
//			Field[] sufd = superClass.getDeclaredFields();
//			Collections.addAll(flist, sufd);
//		}
//		Field[] sufd = entityClazz.getDeclaredFields();
//		Collections.addAll(flist, sufd);
//		Field[] fields = FieldUtils.getAllFields(entityClazz);
		List<Field> flist = FieldUtils.getAllFieldsList(entityClazz);
		
		Map<String, FieldDoc> maps = new LinkedHashMap<>();
		String bodykey = "body";
		String bodyType = "bodyType";

		
			for (Field f : flist) {
				
				
				if (superclass || f.getDeclaringClass().toString().lastIndexOf("$") > 0) {
					
					DocDesc head = AnnotationUtils.findAnnotation(f.getDeclaringClass(), DocDesc.class);
					if(head == null){continue;}
					dataMap.put("url", head.url());
					dataMap.put("urldesc", head.desc());
					dataMap.put(bodykey, head.body());
					dataMap.put("urlNo", index);
					dataMap.put(bodyType, head.type());
					
					DocDesc meta = f.getAnnotation(DocDesc.class); 
					FieldDoc doc = new FieldDoc(meta,f);
					maps.put(f.getName(), doc);
				}
			}
		
		index ++;
		StringBuffer str = new StringBuffer(); // sql 条件
		String temp = "  %s|  %s|  %s|  %s";
		String result = String.format(temp, formatStr("参数", 19), formatStr("类型", 9),formatStr("必填", 5),"说明");
		str.append(result).append("\n");
		result = String.format(temp, formatStr("----", 20), formatStr("----", 10),formatStr("----", 6),"----");
		str.append(result).append("\n");
		for (String key : maps.keySet()) {
			FieldDoc doc = maps.get(key);
			String key2 = formatStr(doc.getName(), 20);
			String value = formatStr(subString(doc.getTypeName()), 10);
			if(doc.getDesc() == null){
			    continue;
            }
			String fill = formatStr(subString(doc.getDesc().fill()), 6);
		
			result = String.format(temp, key2,value,fill,doc.getDesc().desc());
			System.out.println(result);
			str.append(result).append("\n");
			
		}
		System.out.println(str.toString());
		dataMap.put("request", str.toString());
		Object clazz = dataMap.get(bodykey);
		
		
		
		StringBuffer response = new StringBuffer(); // sql 条件
		String rspresult = String.format(temp, formatStr("参数", 19), formatStr("类型", 8),formatStr("必填", 5),"说明");
		response.append(rspresult).append("\n");
		rspresult = String.format(temp, formatStr("----", 20), formatStr("----", 10),formatStr("----", 6),"----");
		response.append(rspresult).append("\n");
		if( clazz == JsonParse.class ){
			dataMap.put(bodykey, "");
			dataMap.put("response", response.toString());
		}else{
			if(clazz instanceof Class){
				CreateObject.createClassResult((Class<?>)clazz,dataMap);
			}
			
//			
		}
		System.out.println(dataMap.toString());
		
		

	}




	/**
	 * 获取字符串的长度，如果有中文，则每个中文字符计为2位
	 * @return 字符串的长度
	 */
	public static int length(String s)
	{
		int length = 0;
		for(int i = 0; i < s.length(); i++)
		{
			int ascii = Character.codePointAt(s, i);
			if(ascii >= 0 && ascii <=255)
				length++;
			else
				length += 2;

		}
		return length;

	}


	public static String formatStr(String str, int length)  {
		if (str == null) {
			str = "";
		}
		str = str.trim();
		int strLen = length(str); // 空格的长度 = 20 - 字段的长度（GBK）。
		if (strLen == length) {
			return str;
		} else if (strLen < length) {
			int temp = length - strLen;
			String tem = "";
			for (int i = 0; i < temp; i++) {
				tem = tem + " ";
			}
			return str + tem;
		} else {
			return str;
		}
	}

	 static String subString(String str){
		if(str.contains(str)){
			str = str.substring(str.lastIndexOf(".")+1, str.length());
		}
		return str;
	}
	public static void createServerImpl() throws Exception {
		String currentPath = new StringBuilder(System.getProperty("user.dir").replaceAll("\\\\","/")).append("/gc-base-global/doc/").toString();
		String outCacheFileName = currentPath +dataMap.get("module")+"/"+dataMap.get("commentFileName");
		if(!new File(outCacheFileName).exists()){
		    throw new Exception(outCacheFileName+"文件不存在！");
        }
		FreemakerUtil.writeTempDoc(dataMap, "template_doc.md", outCacheFileName);

	}

	public static void createDataTableMd(){
		List<String> tableList = GenerationClassUtil.getDataTableList();
		for(String table : tableList){
			createDateMd(table);
			String currentPath = new StringBuilder(System.getProperty("user.dir").replaceAll("\\\\","/")).append("/gc-base-global/doc/").toString();
			String outCacheFileName = currentPath+"/datasource.md" ;
			FreemakerUtil.writeTempDoc(dataMap, "template_database.md", outCacheFileName);
			index++;
		}
//		createDateMd("rf_user");


	}
	public static  void createDateMd(String tableName){
		StringBuffer str = new StringBuffer(); // sql 条件
		String temp = "  %s | %s | %s | %s | %s | %s";
//		str.append("数据库表名称：" + tableName).append("\n");

		String result = String.format(temp, formatStr("序列号", 10), formatStr("数据字段名称", 30),
				formatStr("类型", 16),formatStr("长度", 10),
				formatStr("描述信息", 50), formatStr("必填", 6));
		str.append(result).append("\n");
		result = String.format(temp, formatStr("----", 10), formatStr("----", 30),
				formatStr("----", 16),formatStr("----", 10)
				 ,formatStr("----", 50),formatStr("----", 6));
		str.append(result).append("\n");
		List<DataDictionaryInfo> list = GenerationClassUtil.getDataDictionaryInfoList(tableName);
		for(DataDictionaryInfo data : list){
			result = String.format(temp, formatStr(data.getColumnNum()+"", 10), formatStr(data.getColumnName(), 30),
					formatStr(data.getColumnType(), 16),formatStr(data.getColumnLength()+"",10),
					formatStr(data.getColumnDesc(), 50),   formatStr(data.getIsNull(), 6));
			str.append(result).append("\n");
		}
		dataMap.put("table_number", index);
		dataMap.put("table_name", tableName);
		dataMap.put("table_info", str.toString());


	}

}
